package communication;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.SocketException;

import exception.ParseException;

public class ConnectionHandle {

	private DataOutputStream out;
	private DataInputStream in;
	
	public ConnectionHandle(DataInputStream input, DataOutputStream output) {
		this.setOutStream(output);
		this.setInStream(input);
	}
	
	public void close() throws IOException {
		getInStream().close();
		getOutStream().close();
	}
	
	public void send(Message msg) throws IOException {
		byte[] toSend = msg.toString().getBytes();
		getOutStream().write(toSend);
		getOutStream().flush();
	}

	public String receive() throws ParseException, SocketException {

		int curr;
		char[] buf = new char[1024];
		int i = 1;
		try {
			while (i < 5) {
				curr = getInStream().read();
				i = headerMessage((char) curr, i);
				buf[i - 1] = (char) curr;
			}

			char beginMsg[] = new char[8];
			while (!beginMessage(beginMsg)) {
				curr = getInStream().read();
				for (int k = 1; k < beginMsg.length; k++)
					beginMsg[k - 1] = beginMsg[k];
				beginMsg[7] = (char) curr;
				buf[i] = (char) curr;
				i++;
			}

			boolean cont = false;

			do {
				curr = getInStream().read();
				buf[i] = (char) curr;
				i++;
				if ((char) curr == '>')
					cont = true;
			} while ((char) curr != '>' && (char) curr != '/');

			if (cont) {

				char endMsg[] = new char[10];

				while (!endMessage(endMsg)) {
					curr = getInStream().read();
					for (int k = 1; k < endMsg.length; k++)
						endMsg[k - 1] = endMsg[k];
					endMsg[9] = (char) curr;
					buf[i] = (char) curr;
					i++;
				}
			} else {
				char endTag[] = new char[2];

				do {
					curr = getInStream().read();
					for (int k = 1; k < endTag.length; k++)
						endTag[k - 1] = endTag[k];
					endTag[endTag.length - 1] = (char) curr;
					buf[i] = (char) curr;
					i++;
				} while ((char) curr != '>'); 
			}

		} catch (SocketException e) {
			throw new SocketException("Connection interrupted.");
		}
		catch (IOException e) {
			e.printStackTrace();
			throw new ParseException("Bad XML file or connection error!");
		}

		return new String(buf);
	}

	private int headerMessage(char c, int i) {
		if (c == '<')
			return 1;
		if (c == '?')
			return 2;
		if (c == 'x')
			return 3;
		if (c == 'm')
			return 4;
		if (c == 'l')
			return 5;
		return i;
	}

	private boolean beginMessage(char[] c) {
		return new String(c).equalsIgnoreCase("<message");
	}

	private boolean endMessage(char[] c) {
		return new String(c).equalsIgnoreCase("</message>");
	}

	public DataOutputStream getOutStream() {
		return out;
	}

	public void setOutStream(DataOutputStream out) {
		this.out = out;
	}

	public DataInputStream getInStream() {
		return in;
	}

	public void setInStream(DataInputStream in) {
		this.in = in;
	}

}
